// * uni - app蓝牙连接的整个流程 *
// 	1、 初始化蓝牙 uni.openBluetoothAdapter(OBJECT) *
// 	2、 开始搜索蓝牙设备 uni.startBluetoothDevicesDiscovery(OBJECT) *
// 	3、 发现外围设备 uni.onBluetoothDeviceFound(CALLBACK) *
// 	4、 停止搜寻附近的蓝牙外围设备 uni.stopBluetoothDevicesDiscovery(OBJECT) *
// 	5、 连接低功耗蓝牙设备 uni.createBLEConnection(OBJECT) *
// 	6、 获取蓝牙设备所有服务 uni.getBLEDeviceServices(OBJECT) *
// 	7、 获取蓝牙特征 uni.getBLEDeviceCharacteristics(OBJECT) *
// 	8、 启用蓝牙设备特征值变化时的 notify 功能 uni.notifyBLECharacteristicValueChange(OBJECT) *
// 	9、 监听低功耗蓝牙设备的特征值变化 uni.onBLECharacteristicValueChange(CALLBACK) *
// 	10、 对需要操作的特征值进行读、 写操作

import store from '@/store/index.js'
let _self;
export default class Bluetooth {
	constructor() {
		_self = this;
		_self.deviceId = "";
		_self.blueDeviceList = [];
		_self.isConnect = false; //是否已连接
		_self.isStop = false; //是否停止搜所
		_self.UUID_SERVICE = '0000FEE0-0000-1000-8000-00805F9B34FB'; //服务UUID，设备方提供
		_self.UUID_CHAR = '0000FEE1-0000-1000-8000-00805F9B34FB'; //特征值UUID，设备方提供
	}
	/* 初始化并搜索蓝牙操作 */
	initEventDevice() {
		uni.showLoading({
			title: "蓝牙连接中"
		})

		/* 1、初始化蓝牙 uni.openBluetoothAdapter(OBJECT) */
		uni.openBluetoothAdapter({
			complete: () => {
				/* 监听蓝牙是否开启*/
				uni.onBluetoothAdapterStateChange(function(res) {
					//res.available 蓝牙适配器是否可用
					//res.discovering 蓝牙适配器是否处于搜索状态
					console.log('适配器状态变化', res)

					if (!res.available && !res.discovering) {
						_self.isStop = false;
						uni.showToast({
							duration: 2500,
							title: "请打开手机蓝牙",
							icon: 'error',
						})
						store.commit('updateStatus', false);
					} else if (_self.isStop == false && res.available && !res.discovering) {
						console.log("蓝牙已开启，可以执行搜索操作")
						_self.initEventDevice();
					} else if (res.available && res.discovering) {
						console.log("蓝牙已开启，并且正在搜索中")
					}
				})
			},
			success: (res) => {
				/* 初始化蓝牙成功 */
				/* 2、开始搜索蓝牙设备 uni.startBluetoothDevicesDiscovery(OBJECT) */
				/* 监听蓝牙适配器状态变化事件  可以检测当前设备的蓝牙的断开或者连接的情况*/
				_self.startBluetoothDevicesDiscovery();
				// _self.connectTimeout();

			},
			fail: (res) => {
				console.log("初始化蓝牙失败:" + JSON.stringify(res))
				uni.hideLoading();
				uni.showToast({
					duration: 2500,
					title: "请打开手机蓝牙",
					icon: 'error',
				})
			}
		})
	}
	/*搜索蓝牙*/
	startBluetoothDevicesDiscovery() {
		uni.startBluetoothDevicesDiscovery({
			allowDuplicatesKey: false, //是否允许同一设备多次上报，但RSSI值会有所不同
			success: (res) => {
				console.log("搜索成功:" + JSON.stringify(res))
				_self.onBluetoothDeviceFound();
			},
			fail: (res) => {
				uni.showModal({
					title: '蓝牙连接失败了哦',
					content: `
                        1、请查看周围是否有连接此设备的蓝牙；
                        2、请先关闭手机蓝牙在打开一次；
                        3、请检查位置信息是否打开；
                        4、退出小程序重新扫码进入。`,
					showCancel: false,
					confirmText: "我知道了",
					success: () => {}
				})
				console.log("搜索失败:" + JSON.stringify(res))
			}
		})
	}

	/* 搜索蓝牙设备回调 */
	onBluetoothDeviceFound() {
		uni.onBluetoothDeviceFound(function(res) {
			if (res.devices[0].name) {
				console.log(res, '---')
				_self.blueDeviceList.push(res.devices[0])
			}
			/* 每次遍历指定设备，一旦搜索到指定设备就结束搜索*/

			// let bluename = JSON.parse(uni.getStorageSync('deviceInfo')).bluename; //需要搜索的设备名称
			// /* 搜索过程中如果搜索到需要的设备，就停止搜索 */
			// CALLBACK.devices.forEach(device => {
			// 	/* 筛选需要的deviceId */
			// 	if (device.deviceId === bluename) {
			// 		//找到需要的设备之后，停止搜索
			// 		console.log("搜索到指定设备==" + device.deviceId)
			// 		_self.isConnect = true;
			// 		/*停止搜索*/
			// 		_self.stopBluetoothDevicesDiscovery();
			// 		/* 执行连接 */
			// 		_self.connectDevice(device.deviceId);
			// 	}
			// })
		})
	}

	/*设置蓝牙搜索时间30秒, 如果超时没有搜索到就停止搜索*/
	connectTimeout() {
		setTimeout(() => {
			if (!_self.isConnect) {
				uni.hideLoading();
				_self.stopBluetoothDevicesDiscovery();
				uni.showModal({
					title: '蓝牙连接失败了哦',
					content: `
                        1、请查看周围是否有连接此设备的蓝牙；
                        2、请先关闭手机蓝牙在打开一次；
                        3、请检查位置信息是否打开；
                        4、退出小程序重新扫码进入。`,
					showCancel: false,
					confirmText: "我知道了",
					success: () => {}
				})
			}
		}, 30000)
	}

	/* 停止搜索 */
	stopBluetoothDevicesDiscovery() {
		uni.stopBluetoothDevicesDiscovery({
			complete: () => {
				_self.isStop = true;
			},
			success: (res) => {
				console.log("停止搜索成功")
			},
			fail: (res) => {
				console.log("停止失败")
				uni.hideLoading();
			}
		})
	}

	/* 连接低功耗蓝牙 */
	connectDevice(deviceId) {
		console.log("执行到这里了")
		uni.createBLEConnection({
			deviceId, //点击的DeviceId
			timeout: 5000,
			success: (res) => {
				console.log("连接成功")
				_self.deviceId = deviceId;
				/* 这边获取全部的服务，并筛选出当前需要的*/
				_self.getBLEDeviceServices(deviceId)

			},
			fail: (error) => {
				/* 连接失败 */
				uni.hideLoading();
				console.log("连接失败")
				console.log(error);
				uni.showModal({
					title: '蓝牙连接失败了哦',
					content: `
                        1、请查看周围是否有连接此设备的蓝牙；
                        2、请先关闭手机蓝牙在打开一次；
                        3、请检查位置信息是否打开；
                        4、退出小程序重新扫码进入。`,
					showCancel: false,
					confirmText: "我知道了",
					success: () => {}
				})
			}
		})
		/* 监听蓝牙设备的连接状态 */
		uni.onBLEConnectionStateChange(function(res) {
			console.log(res.deviceId + "连接状态:" + res.connected)
		})
	}

	/* 获取所有的服务*/
	getBLEDeviceServices(deviceId) {
		console.log("开始获取服务")
		//连接成功之后需要延时，继续操作才不会出问题,延时时间短一点都没关系，我这边用了1秒
		setTimeout(() => {
			uni.getBLEDeviceServices({
				// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
				deviceId,
				success: (res) => {
					console.log('device services:', res)
					res.services.forEach((item) => {
						//这里微信小程序获取的服务ID是大写，支付宝是小写，所以统一转换为大写
						let serviceId = item.uuid.toUpperCase();

						if (serviceId == _self.UUID_SERVICE) {
							console.log('serverId:', serviceId)
							/* 进入特征值 */
							_self.getBLEDeviceCharacteristics(deviceId, serviceId);
						}
					})
				},
				fail: (error) => {
					console.log("获取服务失败")
					console.log(error)
					uni.hideLoading();
				}
			})
		}, 1000)
	}

	/* 获取所有特征值 */
	getBLEDeviceCharacteristics(deviceId, serviceId) {
		console.log("开始获取特征")
		setTimeout(() => {
			uni.getBLEDeviceCharacteristics({
				deviceId,
				serviceId,
				success: (res) => {
					console.log(res)
					res.characteristics.forEach((item) => {
						console.log(item)
						//这里跟服务ID一样，支付宝需要转换为大写
						//#ifdef MP-ALIPAY
						let characterId = item.characteristicId.toUpperCase();
						//#endif
						//#ifdef MP-WEIXIN
						let characterId = item.uuid;
						//#endif
						/* 只要用到的唤醒即可 */
						if (characterId == _self.UUID_CHAR) {
							console.log('characteristicId:', characterId)
							_self.notifyBLECharacteristicValueChange(deviceId,
								serviceId, characterId)
						}
					})
				},
				fail: (res) => {
					uni.hideLoading();
					console.log(res)
				}
			})
		}, 1000)
	}
	/* 启用蓝牙设备特征值变化时的 notify 功能 */
	notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
		console.log("开始唤醒")
		uni.notifyBLECharacteristicValueChange({
			state: true, // 启用 notify 功能
			// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
			deviceId,
			// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
			serviceId,
			// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
			characteristicId,
			success: (res) => {
				uni.hideLoading();
				/* 连接成功 */
				uni.showToast({
					title: "连接成功",
					icon: 'success'
				});
				//储存蓝牙连接状态
				store.commit('updateStatus', true);

				console.log('notifyBLECharacteristicValueChange success', res.errMsg)
				/* 连接成功以后，执行设置的操作，并且打开返回值的监听开关并监听 */
				//获取设备信息
				let DeviceCommand = "01,02,03,04," + func("01020304") + ",1E";
				let DeviceArrayBuffer = string2buffer(DeviceCommand);
				_self.writeDevice(DeviceArrayBuffer);

				//出货后关门延时设置
				let delayedCommand = "01,02,03,04,0A," + func("010203040A") + ",1E";
				let delayedArrayBuffer = string2buffer(delayedCommand);
				_self.writeDevice(delayedArrayBuffer);

				/* 监听低功耗蓝牙设备的特征值变化 */
				uni.onBLECharacteristicValueChange(function(CALLBACK) {
					let result = blueTool.ab2hex(CALLBACK.value);
					console.log("收到的数据值==", result);
					// 这里做一些具体的业务逻辑
					//我这里是监听低功耗蓝牙设备的特征值变化，然后调后台接口获取设备的电量，展示在页面
					if ("73080182" === result.substring(0, 8)) {
						var o = result.substring(8, 10);
						o = parseInt(o, 16);
						let dl = "";
						if (o >= 41) {
							dl = 100;
						} else if (o <= 37) {
							dl = 0;
						} else {
							dl = (o - 37) * 100 / (41 - 37);
						}
						//获取设备电量
						uni.request({
							url: baseUrl + "/api/*****",
							method: "POST",
							data: {
								key: value
							},
							header: {
								"Content-Type": "application/x-www-form-urlencoded"
							},
							success: function(t) {
								store.commit('setDeviceBattery', t.data.data);
								console.log("设备上传回调" + JSON.stringify(t.data));
							},
							fail: function(t) {}
						});
					}
				})
			},
			fail: (res) => {
				uni.hideLoading();
				console.log('notifyBLECharacteristicValueChange success', res.errMsg)
			}
		})
	}
	/* 执行写入命令操作 */
	writeDevice(_Buffer) {
		uni.writeBLECharacteristicValue({
			deviceId: _self.deviceId,
			serviceId: _self.UUID_SERVICE,
			characteristicId: _self.UUID_CHAR,
			value: _Buffer,
			success: (res) => {
				/* 发送成功 */
				console.log('最后一次写入成功', res)
			},
			fail: (error) => {
				/* 发送失败 */
				console.log('最后一次写入失败', error)
			}
		})
	}

	/* 获取本机蓝牙适配器状态 */
	getBluetoothState() {
		uni.getBluetoothAdapterState({
			success: (res) => {
				console.log("状态" + JSON.stringify(res))
			}
		})
	}

	/* 关闭蓝牙适配器*/
	closeBlueAdapter() {
		uni.closeBluetoothAdapter({
			success() {
				console.log("关闭蓝牙适配器成功")
			}
		})
	}

	/* 断开低功耗蓝牙的连接 */
	disconnectBle() {
		uni.closeBLEConnection({
			deviceId: _self.deviceId,
			success: (res) => {
				console.log("断开成功" + res)
				store.commit('updateStatus', false);
				store.commit('setDeviceBattery', 0);
			}
		})
	}

	/* 具体的命令BCC校验*/
	func(t) {
		for (var e = t, a = [], i = 0; i < e.length - 1; i += 2) a.push(e.substring(i, i + 2));
		for (var o = a[0], s = 0; s < a.length - 1; s++) o ^= a[s + 1];
		return o;
	}

	/* 字符串转arraybuffer */
	string2buffer(str) {
		// 首先将字符串转为16进制
		let val = str
		console.log(val)
		// 将16进制转化为ArrayBuffer
		return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) {
			return parseInt(h, 16)
		})).buffer
	}
}